package domain;

import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Logger;

import serverService.Matcher;

public class OrderBook {
	static Logger logger = Logger.getLogger(Matcher.class.getName());
	TreeMap<Double, OrderBookData> map = new TreeMap<Double, OrderBookData>();
	OrderQueue<Order> orderQueue = new OrderQueue<Order>();

	public OrderBook() {
		map = new TreeMap<Double, OrderBookData>();
	}

	public MatchResult addSeller(Order order) {
		if (!map.containsKey(order.getPrice())) {
			OrderBookData obd = new OrderBookData();
			map.put(order.getPrice(), obd);
		}
		map.get(order.getPrice()).addSeller(order);
		return matchToSeller(order);
	}

	public MatchResult addBuyer(Order order) {
		if (!map.containsKey(order.getPrice())) {
			OrderBookData obd = new OrderBookData();
			map.put(order.getPrice(), obd);
		}
		map.get(order.getPrice()).addBuyers(order);
		return matchToBuyer(order);
	}

	public MatchResult matchToSeller(Order order) {
		Boolean matched = false;
		Double price = order.getPrice();
		NavigableMap<Double, OrderBookData> subMap = map.tailMap(price, true);
		MatchResult matchResult = new MatchResult();
		matchResult.setMatched(false);
		for (Entry<Double, OrderBookData> entry : subMap.descendingMap()
				.entrySet()) {
			List<Order> orders = entry.getValue().getBuyers();
			while (orders.iterator().hasNext()) {
				Order buyerOrder = orders.iterator().next();
				
				if (buyerOrder.getAmount() == order.getAmount()) {
					matched = true;
					orders.remove(buyerOrder);
					map.get(order.getPrice()).getSellers().remove(order);
					matchResult.setMatched(true);
					order.setPrice(buyerOrder.getPrice());
					matchResult.setBuyerOrder(buyerOrder);
					matchResult.setSellerOrder(order);
					logger.info("Oders Matched " + order.getStock() + " Owner "
							+ order.getOwner().getName() + " Amount: "
							+ order.getAmount() + " Price: " + order.getPrice()
							+ " WHITH " + buyerOrder.getStock() + " Owner "
							+ buyerOrder.getOwner().getName() + " Amount: "
							+ buyerOrder.getAmount() + " Price: "
							+ buyerOrder.getPrice());
					break;
				}
			}
			if (matched)
				break;
		}

		return matchResult;
	}

	public MatchResult matchToBuyer(Order order) {
		Boolean matched = false;
		Double price = order.getPrice();
		NavigableMap<Double, OrderBookData> subMap = map.headMap(price, true);
		MatchResult matchResult = new MatchResult();
		matchResult.setMatched(false);
		for (Entry<Double, OrderBookData> entry : subMap
				.entrySet()) {
			List<Order> orders = entry.getValue().getSellers();
			while (orders.iterator().hasNext()) {
				Order sellOrder = orders.iterator().next();
				
				if (sellOrder.getAmount() == order.getAmount()) {
					matched = true;
					System.out.println(map.get(order.getPrice()).getBuyers().remove(order));
					System.out.println(orders.remove(sellOrder));
					matchResult.setMatched(true);
					order.setPrice(sellOrder.getPrice());
					matchResult.setBuyerOrder(order);
					matchResult.setSellerOrder(sellOrder);
					logger.info("Oders Matched " + order.getStock() + " Owner "
							+ order.getOwner().getName() + " Amount: "
							+ order.getAmount() + " Price: " + order.getPrice()
							+ " WHITH " + sellOrder.getStock() + " Owner "
							+ sellOrder.getOwner().getName() + " Amount: "
							+ sellOrder.getAmount() + " Price: "
							+ sellOrder.getPrice());
					break;
				}
			}
			if (matched)
				break;
		}

		return matchResult;
	}
}
